package com.songlanyun.modules.sharebenefitconfig.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.songlanyun.common.enums.CommonwealConstant;
import com.songlanyun.common.enums.GoodsConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.BeanUtil;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;
import com.songlanyun.common.utils.custom.ClassConvertUtils;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.modules.cnarea.entity.CnArea;
import com.songlanyun.modules.exception.ConfigException;
import com.songlanyun.modules.sharebenefitconfig.dao.CommonwealShareBenefitConfigDao;
import com.songlanyun.modules.sharebenefitconfig.entity.CommonwealShareBenefitConfigEntity;
import com.songlanyun.modules.sharebenefitconfig.model.IShareBenefitConfig;
import com.songlanyun.modules.sharebenefitconfig.model.InviteConfig;
import com.songlanyun.modules.sharebenefitconfig.model.OrdersConfig;
import com.songlanyun.modules.sharebenefitconfig.model.PartnerConfig;
import com.songlanyun.modules.sharebenefitconfig.model.dto.CommonwealShareBenefitConfigDTO;
import com.songlanyun.modules.sharebenefitconfig.service.CommonwealShareBenefitConfigService;
import com.songlanyun.modules.wechat.config.WxMaProperties;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;


@Service("commonwealShareBenefitConfigService")
public class CommonwealShareBenefitConfigServiceImpl extends ServiceImpl<CommonwealShareBenefitConfigDao, CommonwealShareBenefitConfigEntity> implements CommonwealShareBenefitConfigService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CommonwealShareBenefitConfigEntity> page = this.page(
                new Query<CommonwealShareBenefitConfigEntity>().getPage(params),
                new QueryWrapper<CommonwealShareBenefitConfigEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(CommonwealShareBenefitConfigDTO dto) {
        CommonwealShareBenefitConfigEntity entity = new CommonwealShareBenefitConfigEntity();
        entity.setType(CommonwealConstant.ShareBenefitConfigType.getByCode(dto.getType()));
        if (ObjectUtil.isEmpty(dto.getConfig())) {
            throw new RRException(ConfigException.CONFIG_VALUE_NOT_EXIST);
        }

        switch (entity.getType()) {
            case PARTNER_CONFIG:
                List<PartnerConfig> partnerConfigs = ClassConvertUtils.castList(dto.getConfig(), PartnerConfig.class);
                if (CollectionUtil.isNotEmpty(partnerConfigs)) {
                    partnerConfigs.forEach(c -> {
                        ValidatorUtils.validateEntity(c);
                    });
                }
                entity.setJsonData(ClassConvertUtils.transformJSONToSnake(dto.getConfig()));
                break;
            case INVITE_CONFIG:
                InviteConfig inviteConfig = ClassConvertUtils.transformObject(dto.getConfig(), InviteConfig.class);
                if (ObjectUtil.isNotNull(inviteConfig)) {
                    ValidatorUtils.validateEntity(inviteConfig);
                }
                entity.setJsonData(ClassConvertUtils.transformJSONToSnake(dto.getConfig()));
                break;
            case ORDERS_CONFIG:
                OrdersConfig ordersConfig = ClassConvertUtils.transformObject(dto.getConfig(), OrdersConfig.class);
                if (ObjectUtil.isNotNull(ordersConfig)) {
                    ValidatorUtils.validateEntity(ordersConfig);
                }
                entity.setJsonData(ClassConvertUtils.transformJSONToSnake(dto.getConfig()));
                break;
            default:
                throw new RRException(ConfigException.CONFIG_NOT_EXIST);
        }

        CommonwealShareBenefitConfigEntity one = this.lambdaQuery().eq(CommonwealShareBenefitConfigEntity::getType, entity.getType()).one();
        if (ObjectUtil.isNotNull(one)) {
            entity.setId(one.getId());
        }
        this.saveOrUpdate(entity);
    }

    @Override
    public IShareBenefitConfig getByType(CommonwealConstant.ShareBenefitConfigType type) {
        CommonwealShareBenefitConfigEntity entity = this.loadByType(type, false);
        if (ObjectUtil.isNotNull(entity)) {
            return this.stringToClassByType(type, entity.getJsonData());
        }

        return null;
    }

    @Override
    public CommonwealShareBenefitConfigEntity loadByType(CommonwealConstant.ShareBenefitConfigType type, boolean tw) {
        CommonwealShareBenefitConfigEntity one = this.lambdaQuery().eq(CommonwealShareBenefitConfigEntity::getType, type).last("limit 1").one();
        if (ObjectUtil.isNull(one) && tw) {
            throw new RRException(ConfigException.CONFIG_NOT_EXIST);
        }
        return one;
    }

    @Override
    public PartnerConfig.CommonwealPartnerConfig getPartnerConfigByQualification(GoodsConstant.ServicePackageArea qualification) {
        if (ObjectUtil.isNull(qualification)) {
            return null;
        }
        CommonwealShareBenefitConfigEntity entity = this.loadByType(CommonwealConstant.ShareBenefitConfigType.PARTNER_CONFIG, false);
        if (ObjectUtil.isNotNull(entity)) {
            try {
                PartnerConfig partnerConfig = ClassConvertUtils.stringToClassSnake(entity.getJsonData(), new TypeReference<PartnerConfig>() {
                });
                List<PartnerConfig.CommonwealPartnerConfig> list = partnerConfig.getList();
                Optional<PartnerConfig.CommonwealPartnerConfig> firstConfig = list.stream().filter(p -> NumberUtil.equals(p.getQualification(), qualification.getCode())).findFirst();
                if (firstConfig.isPresent()) {
                    return firstConfig.get();
                }
            } catch (IOException e) {
                throw new RRException("类型转换失败");
            }
        }
        return null;
    }

    @Override
    public Integer getServicePointsRatio() {
        CommonwealShareBenefitConfigEntity entity = this.loadByType(CommonwealConstant.ShareBenefitConfigType.INVITE_CONFIG, false);
        if (ObjectUtil.isNotNull(entity)) {
            try {
                InviteConfig inviteConfig = ClassConvertUtils.stringToClassSnake(entity.getJsonData(), new TypeReference<InviteConfig>() {
                });
                if (ObjectUtil.isNotNull(inviteConfig)) {
                    return inviteConfig.getServicePointsRatio();
                }

            } catch (IOException e) {
                throw new RRException("类型转换失败");
            }
        }
        return null;
    }

    @Override
    public Integer getOrderRatio() {
        CommonwealShareBenefitConfigEntity entity = this.loadByType(CommonwealConstant.ShareBenefitConfigType.ORDERS_CONFIG, false);
        if (ObjectUtil.isNotNull(entity)) {
            try {
                OrdersConfig ordersConfig = ClassConvertUtils.stringToClassSnake(entity.getJsonData(), new TypeReference<OrdersConfig>() {
                });
                if (ObjectUtil.isNotNull(ordersConfig)) {
                    return ordersConfig.getOrderRatio();
                }

            } catch (IOException e) {
                throw new RRException("类型转换失败");
            }
        }
        return null;
    }

    @Override
    public List<CommonwealShareBenefitConfigEntity> queryList() {
        List<CommonwealShareBenefitConfigEntity> list = this.lambdaQuery().list();
        list.forEach(c -> {
            c.setConfig(this.stringToClassByType(c.getType(), c.getJsonData()));
        });

        return list;
    }

    private IShareBenefitConfig stringToClassByType(CommonwealConstant.ShareBenefitConfigType type, String jsonData) {
        try {
            switch (type) {
                case PARTNER_CONFIG:
                    return ClassConvertUtils.stringToClassSnake(jsonData, new TypeReference<PartnerConfig>() {
                    });
                case INVITE_CONFIG:
                    return ClassConvertUtils.stringToClassSnake(jsonData, new TypeReference<InviteConfig>() {
                    });
                case ORDERS_CONFIG:
                    return ClassConvertUtils.stringToClassSnake(jsonData, new TypeReference<OrdersConfig>() {
                    });
                default:
                    throw new RRException(ConfigException.CONFIG_NOT_EXIST);
            }
        } catch (IOException e) {
            throw new RRException("类型转换失败");
        }
    }

}
